﻿using Frameworks;
using Network.Core.RPC;
using Network.FrameSync;
using Network.General.Server;
using System.Collections.Generic;
using System.Text;
using UnityEngine;

namespace Server
{
    public class RoomManager : Singleton<RoomManager>
    {
        private NetManager _net;
        private List<Room> _listRoom = new List<Room>();

        private RoomManager() { }

        public override void OnSingletonInit()
        {
            base.OnSingletonInit();
        }

        public override void Dispose()
        {
            _net.Clean();

            base.Dispose();
        }

        public void Init(ServerContext context)
        {
            _net = context.net;
            _net.Rpc.RegisterListener(this);
        }

        public void Dump()
        {
            StringBuilder sb = new StringBuilder();
            Room[] list = _listRoom.ToArray();
            for (int i = 0; i < list.Length; i++)
            {
                sb.AppendLine("\t" + list[i].DumpString("\t"));
            }

            Debug.LogWarning(string.Format("\nRooms ({0}):\n{1}", _listRoom.Count, sb));
        }

        [RPCRequest]
        private void GetRoomList(ISession session)
        {
            List<RoomData> list = new List<RoomData>();
            for (int i = 0; i < _listRoom.Count; i++)
            {
                list.Add(_listRoom[i].data);
            }
            RoomListData data = new RoomListData();
            data.rooms = list;
            _net.Rpc.Return(data);
        }

        [RPCRequest]
        private void CreateRoom(ISession session, uint userId, string roomName)
        {
            Room room = new Room();
            UserData ud = OnlineManager.Instance.GetUserData(userId);
            room.Create(userId, ud.account, session, roomName);

            _listRoom.Add(room);

            _net.Rpc.Return(room.data);
        }

        [RPCRequest]
        private void JoinRoom(ISession session, uint userId, uint roomId)
        {
            Room room = GetRoom(roomId);
            if (room != null)
            {
                if (room.GetPlayerCount() < room.data.maxPlayers)
                {
                    UserData ud = OnlineManager.Instance.GetUserData(userId);

                    room.AddPlayer(userId, ud.account, session);
                    ISession[] listSession = room.GetSessionList();
                    _net.Rpc.Invoke(listSession, "NotifyRoomUpdate", room.data);

                    _net.Rpc.Invoke(listSession, "NotifyRoomNotAllReady", (int)roomId);
                }
                else
                {
                    _net.Rpc.ReturnError("房间已经满员", (int)roomId);
                }
            }
            else
            {
                _net.Rpc.ReturnError("房间不存在", (int)roomId);
            }
        }

        [RPCRequest]
        private void ExitRoom(ISession session, uint userId, uint roomId)
        {
            Room room = GetRoom(roomId);
            if (room != null)
            {
                room.RemovePlayer(userId);

                if (room.GetPlayerCount() > 0)
                {
                    ISession[] listSession = room.GetSessionList();
                    _net.Rpc.Invoke(listSession, "NotifyRoomUpdate", room.data);
                }
            }
        }

        [RPCRequest]
        private void RoomReady(ISession session, uint userId, uint roomId, bool ready)
        {
            Room room = GetRoom(roomId);
            if (room != null)
            {
                room.SetReady(userId, ready);
                ISession[] listSession = room.GetSessionList();
                _net.Rpc.Invoke(listSession, "NotifyRoomUpdate", room.data);

                if (room.IsAllReady())
                {
                    _net.Rpc.Invoke(listSession, "NotifyRoomIsAllReady", (int)roomId);
                }
                else
                {
                    _net.Rpc.Invoke(listSession, "NotifyRoomNotAllReady", (int)roomId);
                }
            }
            else
            {
                _net.Rpc.ReturnError("房间不存在", (int)roomId);
            }
        }

        [RPCRequest]
        private void StartGame(ISession session, uint userId, uint roomId)
        {
            Room room = GetRoom(roomId);
            if (room != null)
            {
                if (room.data.owner == userId)
                {
                    if (room.CanStartGame())
                    {
                        //FSPParam param = room.GetGameStartParam();
                        //ISession[] listSession = room.GetSessionList();
                        //_net.Rpc.Invoke(listSession, "NotifyGameStart", param);

                        List<uint> listPlayerId = new List<uint>();
                        for (int i = 0; i < room.data.players.Count; i++)
                        {
                            listPlayerId.Add(room.data.players[i].id);
                        }

                        int authId = Network.Math.Random.Default.Seed;

                        GameServerStartParam param = new GameServerStartParam();
                        param.roomId = roomId;
                        param.authId = authId;
                        param.listPlayerId = listPlayerId;

                        _net.Rpc.Return(param);
                    }
                    else
                    {
                        // 还有玩家未准备
                    }
                }
                else
                {
                    // 只有房主可以启动游戏
                }
            }
            else
            {
                _net.Rpc.ReturnError("房间不存在", (int)roomId);
            }
        }

        [RPCRequest]
        private void OnCreateGame(ISession session, FSPParam fspParam, GameServerStartParam gameStartParam)
        {
            Room room = GetRoom(gameStartParam.roomId);

            XJGameStartParam param = new XJGameStartParam();
            param.fspParam = fspParam;
            param.gameParam = room.GetGameStartParam();
            param.players = room.data.players;

            // 因为每一个玩家的FSPParam中SessionId都不一样,所以分来赋值
            for (int i = 0; i < gameStartParam.listPlayerId.Count; i++)
            {
                PlayerData player = param.players[i];
                param.fspParam.sid = gameStartParam.listPlayerFSPSessionId[i];
                ISession sessionTemp = room.GetSession(player.userId);
                _net.Rpc.Invoke(sessionTemp, "NotifyGameStart", param);
            }
            //ISession[] listSession = room.GetSessionList();
            //_net.Rpc.Invoke(listSession, "NotifyGameStart", param);
        }

        private Room GetRoom(uint id)
        {
            for (int i = 0; i < _listRoom.Count; i++)
            {
                if (_listRoom[i].data.id == id)
                {
                    return _listRoom[i];
                }
            }
            return null;
        }
    }
}